package com.hwtx.form.domain.meta;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.hwtx.form.domain.listener.DataModelChangeEvent;
import com.hwtx.form.domain.listener.FormConfigChangeEvent;
import com.hwtx.form.domain.repo.FormConfigRepo;
import com.hwtx.form.domain.repo.FormRepo;
import com.hwtx.form.domain.vo.FormConfigQuerySearchVo;
import com.hwtx.form.domain.vo.FormConfigQueryVo;
import com.hwtx.form.persistence.entity.FormDefDetail;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.ExecutionException;

@Component
@Slf4j
public class FormConfigMeta {
    protected final Cache<Long, List<FormConfigQueryVo>> formQueryConfigCache = CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(10)).build();
    protected final Cache<Long, FormDefDetail> formDefDetailCache = CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(10)).build();

    @Resource
    private FormConfigRepo formConfigRepo;
    @Resource
    private FormRepo formRepo;

    @EventListener
    public void clearQueryConfigCache(FormConfigChangeEvent formConfigChangeEvent) {
        formQueryConfigCache.invalidate(formConfigChangeEvent.getFormId());
        formDefDetailCache.invalidate(formConfigChangeEvent.getFormId());
    }

    @EventListener
    public void dataModelChange(DataModelChangeEvent event) {
        log.info("DefaultFormBaseHandle dataModelChange event:{}", event);
        List<FormDefDetail> formDefDetails = formConfigRepo.getFormDetailByModelName(event.getModelName());
        formDefDetails.forEach(item -> formQueryConfigCache.invalidate(item.getFormId()));
    }

    public FormDefDetail getFormDefDetail(Long formId) throws ExecutionException {
        return formDefDetailCache.get(formId, () -> {
            Long fId = formId;
            String appendTo = formRepo.getFormDef(formId).getMeta().getAppendTo();
            if (StringUtils.isNotEmpty(appendTo)) {
                fId = Long.parseLong(appendTo);
            }
            return formConfigRepo.getFormDetail(fId);
        });
    }

    public List<FormConfigQueryVo> getFormConfigQueries(Long formId) throws ExecutionException {
        return formQueryConfigCache.get(formId, () -> {
            Long fId = formId;
            Long appendTo = formRepo.getAppendToFormId(formId);
            if (appendTo != null) {
                fId = appendTo;
            }
            return formConfigRepo.listMergedFormConfig(FormConfigQuerySearchVo.builder().formId(fId).build());
        });
    }
}
